----------Math Tutor: Decimals---------
A 4am crack                  2015-12-27
---------------------------------------

Name: Math Tutor: Decimals
Version: June 18, 1987
Genre: educational
Year: 1988
Authors: Michael Maloney, Michael
  Summers, Pat Stuart
Publisher: Scholastic
OS: DOS 3.3
Media: one double-sided 5.25" floppy
Previous cracks: none
Identical cracks:
  #535 Peter and the Wolf
  #528 Creatures of the Night
  #527 Birds
  #521 Introduction to Counting
  #510 KidWriter 1.0
  #468 Reading Fun: Beginning Consonant
       Sounds
  #456 Adding Fractions
  #437 Word Master
  #412 Math Class Level 5
  #289 Peter Rabbit Reading

Side A is protected but bootable.
Side B is unprotected by unbootable.
Life is like that.
This has not been a haiku.

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate disk read error

Locksmith Fast Disk Backup
  unable to read any track

EDD 4 bit copy (no sync, no count)
  no errors, but copy grinds on boot

Copy ][+ nibble editor
  modified address epilogue "AF FF FF"
  odd-numbered tracks (1, 3, 5...) also
    have a modified address prologue
    ("D4 AA 96")

Disk Fixer
  ["O" -> "Input/Output Control"]
  set Address Epilogue to "AF FF FF"
  -> even-numbered tracks readable
  T00 looks like a DOS 3.3 RWTS
  set Address Prologue to "D4 AA 96"
  -> odd-numbered tracks also readable
  T01 readable. Also T03, T05, T07...
  T11 looks like a DOS 3.3 disk catalog
  T01,S09 -> startup program is "HELLO"

Why didn't COPYA work?
  modified prologue and epilogue

Why didn't Locksmith FDB work?
  modified prologue and epilogue

Why didn't my EDD copy work?
  I don't know. Maybe a nibble check
  during boot?

Next steps:

  1. capture RWTS with AUTOTRACE
  2. convert disk to standard format
     with Advanced Demuffin
  3. patch RWTS to read demuffin'd disk
  4. find the nibble check & bypass it
  5. declare victory(*)

(*) Take a nap.

                   ~

               Chapter 1
         Bit Math Is Best Math


[S6,D1=original disk]
[S6,D2=blank disk]
[S5,D1=my work disk]

]PR#5
...
CAPTURING BOOT0
...reboots slot 6...
...reboots slot 5...
SAVING BOOT0
/!\ BOOT0 JUMPS TO $08F0
CAPTURING BOOT1
...reboots slot 6...
...reboots slot 5...
SAVING BOOT1
SAVING RWTS

]BLOAD BOOT0,A$800
]CALL -151
*801L
.
. all normal until...
.
084A-   4C F0 08    JMP   $08F0

*8F0L

08F0-   A9 AA       LDA   #$AA
08F2-   85 31       STA   $31
08F4-   A9 00       LDA   #$00
08F6-   8D F1 B6    STA   $B6F1
08F9-   4C 00 B7    JMP   $B700

I've seen this before. The RWTS uses
zero page $31 to check the second byte
of the address (or data (or both))
prologue (or epilogue (or both)).

*BLOAD RWTS,A$2800
*FE89G FE93G     ; disconnect DOS
*B800<2800.2FFFM ; move RWTS into place

*B944L

; routine to read address prologue
B944-   A0 FC       LDY   #$FC
B946-   84 26       STY   $26
B948-   C8          INY
B949-   D0 04       BNE   $B94F
B94B-   E6 26       INC   $26
B94D-   F0 F3       BEQ   $B942
B94F-   BD 8C C0    LDA   $C08C,X
B952-   10 FB       BPL   $B94F

; find prologue nibble #1
B954-   4A          LSR
B955-   C9 6A       CMP   #$6A
B957-   D0 EF       BNE   $B948
B959-   BD 8C C0    LDA   $C08C,X
B95C-   10 FB       BPL   $B959

; find #2
B95E-   C5 31       CMP   $31     <-- !
B960-   D0 F2       BNE   $B954
B962-   A0 03       LDY   #$03
B964-   BD 8C C0    LDA   $C08C,X
B967-   10 FB       BPL   $B964

; find #3
B969-   C9 96       CMP   #$96
B96B-   D0 E7       BNE   $B954

Well this just answers a whole slew of
questions at once.

The code to find prologue nibble #1
explains how this disk can read its
odd-numbered tracks (with non-standard
address prologue "D4 AA 96").

Normal address prologue byte 1 is $D5.
In binary: $D5 = 1101 0101
After LSR:       0110 1010 = $6A

Odd-numbered tracks use $D4 instead.
In binary: $D4 = 1101 0100
After LSR:       0110 1010 = $6A

So this code will match either prologue
and work on both odd and even tracks.

Furthermore, RWTS code is time-critical
between reading the last bit of one
nibble and reading the first bit of the
next. If it's too fast or too slow, it
will get out of phase (because the disk
spins independently of the CPU).

Compare DOS 3.3 (cycle count in margin)

B94F-   BD 8C C0    LDA   $C08C,X
B952-   10 FB       BPL   $B94F
B954-   C9 D5       CMP   #$D5    | 2
B956-   D0 F0       BNE   $B948   | 2 *
B958-   EA          NOP           | 2
B959-   BD 8C C0    LDA   $C08C,X
B95C-   10 FB       BPL   $B959

(*) on the time-critical path, this
    branch is not taken, so always 2

...and this disk's RWTS:

B94F-   BD 8C C0    LDA   $C08C,X
B952-   10 FB       BPL   $B94F
B954-   4A          LSR           | 2
B955-   C9 6A       CMP   #$6A    | 2
B957-   D0 EF       BNE   $B948   | 2 *
B959-   BD 8C C0    LDA   $C08C,X
B95C-   10 FB       BPL   $B959

Despite being more "flexible" (matching
$D5 or $D4), this disk's RWTS uses the
same number of bytes of code and runs
in the same number of cycles. Nice.

Furthermore, look at this code to match
nibble #2 of the address prologue:

*B959L

B959-   BD 8C C0    LDA   $C08C,X
B95C-   10 FB       BPL   $B959
B95E-   C5 31       CMP   $31     <-- !
B960-   D0 F2       BNE   $B954

There's zero page $31, initialized at
$BB00 during boot.

Solution: an IOB module that Advanced
Demuffin calls before calling the
original disk's RWTS. (Read the docs on
my work disk.)

                   ~

               Chapter 2
In Which We Attempt To Use The Original
    Disk As A Weapon Against Itself


*C500G
...
]CALL -151
]BLOAD ADVANCED DEMUFFIN 1.5

; standard Advanced Demuffin setup
; (unchanged)
1400-   4A          LSR
1401-   8D 22 0F    STA   $0F22
1404-   8C 23 0F    STY   $0F23
1407-   8E 27 0F    STX   $0F27
140A-   A9 01       LDA   #$01
140C-   8D 20 0F    STA   $0F20
140F-   8D 2A 0F    STA   $0F2A

; initialize zero page used by the RWTS
1412-   A9 AA       LDA   #$AA
1414-   85 31       STA   $31

; call RWTS
1416-   A9 0F       LDA   #$0F
1418-   A0 1E       LDY   #$1E
141A-   4C 00 BD    JMP   $BD00

*BSAVE IOB $31,A$1400,L$FB

*BRUN ADVANCED DEMUFFIN 1.5

["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B8, load "RWTS" from drive 1

[press "I" to load a new IOB module]
  --> load "IOB $31" from drive 1

["6" to switch to slot 6]

["C" to convert disk]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:...................................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...................................
SC1:...................................
SC2:...................................
SC3:...................................
SC4:...................................
SC5:...................................
SC6:...................................
SC7:...................................
SC8:...................................
SC9:...................................
SCA:...................................
SCB:...................................
SCC:...................................
SCD:...................................
SCE:...................................
SCF:...................................
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

]PR#5
...
]CATALOG,S6,D2

C1983 DSR^C#254
035 FREE

 A 003 HELLO
 B 002 BLOAD LANG
 T 002 H1
 B 002 BEGIN
 B 011 C&J
 B 014 P1
 B 009 P2
 B 013 P3
 B 009 P4
 B 010 TABLS
 B 017 EXTRA
 B 013 HANDLE
 B 034 GRAPHIC
 B 007 A------------------A
 B 045 MODULE
 B 044 SECA
 B 044 SECC
 B 044 SECD
 B 044 SECE
 B 044 SECF
 B 006 MATH TUTOR PAGE
 B 044 SECB

]RUN HELLO
...crashes on loading screen...

[S5,D1=DOS 3.3 system master]

]PR#5
]RUN BOOT,S6,D2
...works...

OK, it doesn't like Diversi-DOS 64K for
some reason. It's probably loading
something into the language card, and
Diversi-DOS has already relocated
itself there. But it works when booted
from standard DOS 3.3, which is good.

The reason I always do this is to see
whether there are any runtime checks
for subtle differences in the original
DOS. If the program runs after booting
from a third-party disk, I can
eliminate a whole range of possible
secondary protections.

[S6,D1=demuffin'd copy]

]PR#6
...works...

Wait, what?

                   ~

               Chapter 3
  In Which We Angrily Investigate Why
    We Suddenly Have A Working Copy


[S6,D1=mysteriously working copy]
[S5,D1=my work disk]

]PR#5
]BLOAD RWTS,A$2800
]CALL -151

*FE89G FE93G
*B800<2800.2FFFM

*B944L
.
. all weirdness accounted for, until...
.
; find epilogue byte #1
B98B-   BD 8C C0    LDA   $C08C,X
B98E-   10 FB       BPL   $B98B
B990-   C9 DE       CMP   #$DE

; if found $DE, immediately exit with
; a "success" status (clear carry bit)
B992-   F0 0A       BEQ   $B99E

; if not $DE, do... this thing
B994-   48          PHA
B995-   68          PLA
B996-   BD 8C C0    LDA   $C08C,X

; Note: no BPL loop here! It only reads
; the data latch once.
B999-   C9 08       CMP   #$08
B99B-   B0 A5       BCS   $B942
B99D-   EA          NOP
B99E-   18          CLC
B99F-   60          RTS

It's looking for a timing bit after the
first epilogue byte. It doesn't even
care what the first epilogue byte was,
as long as it wasn't $DE.

This RWTS will accept two different
address prologues, "D5 AA 96" or "D4 AA
96". It will also accept two different
address epilogues, "DE" or anything-
other-than-DE-followed-by-a-timing-bit.

Why didn't the EDD copy work?
  EDD preserved the original prologue
  epilogue but not the timing bits.
  The prologue checker (at $B944) finds
  "D5 AA 96" (even-numbered tracks) or
  "D4 AA 96" (odd-numbered tracks). But
  the epilogue checker's first compare
  (at $B98B) didn't match because the
  first epilogue byte was still the
  original value ($AF), and its second
  compare (at $B999) didn't match
  because there was no timing bit after
  the first byte. There was never any
  separate nibble check; the structure
  of the disk itself is designed to
  foil nibble copiers.

Why did the demuffin'd copy work?
  Advanced Demuffin wrote out the data
  from each sector onto a standard disk
  that uses "D5 AA 96" prologue and "DE
  AA EB" epilogue. The RWTS always
  matches "D5 AA 96" and doesn't care
  that it never sees a "D4 AA 96" for a
  prologue. The epilogue checker always
  matches "DE" and never checks the
  timing bit. Thus, no RWTS patches are
  necessary.

Quod erat liberandum.

---------------------------------------
A 4am crack                     No. 543
------------------EOF------------------
